package api.utils;

import api.email.EmailContentBean;
import api.interfaceapi.APIMsgParams;
import api.net.RequestBase;
import api.net.RequestURLAPP;
import bean.LoginBean;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeSuite;
import retrofit2.Call;
import retrofit2.Response;
import org.testng.Assert;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import io.qameta.allure.Allure;
public class ToolsAPI<T> implements APIMsgParams {

    public String apiAddressAPI;
    public String paramsAPI;
    public String responseAPI;
    public String apiNameAPI;
    public RequestURLAPP retrofit;
    private EmailContentBean emailContentBean;
    private SimpleDateFormat dateFormat;
    //存放出错接口信息
    public ArrayList<EmailContentBean> list;
    private APIMsgParams APIMsgParams;
    private Gson gson;
    //生成报告时,显示错误原因
    public String errDescription = "";
    //存放请求参数
    public static Map map;
    //异常接口地址
    public static File errefilePath;

    RequestBase requestBase;
    {
        //errefilePath = new File(ToolsAPI.class.getClassLoader().getResource("erreAPI.txt").getFile());
        map = new HashMap<String, Object>();
        requestBase = RequestBase.getInstank();
        retrofit = requestBase.getRetrofit(this);
        list = new ArrayList<>();
        dateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        gson = new Gson();
        setAPIMsgParams(this);
        login();
    }

    public void login() {
        //增加接口请求参数
        put("account", "admin");
        put("password", "666666");
        LoginBean bean = runAPI(retrofit.login(toBody(map)));
        Assert.assertFalse(bean.getData().equals(""),"token返回空字符");
        requestBase.Authorization=bean.getData();
        clearParams();
    }
    //用于在执行每个用例前清空前一次设置的参数
    @AfterMethod
    public void clearParams() {
        map.clear();
        errDescription = "";
        apiAddressAPI = "";
        paramsAPI = "";
        responseAPI = "";
    }

    //设置接口参数
    public void put(String key, Object values) {
        map.put(key, values);
    }

    public void setAPIMsgParams(APIMsgParams APIMsgParams) {
        this.APIMsgParams = APIMsgParams;
    }

    /**
     * 从拦截器拿到接口相关相信
     */
    @Override
    public void getErrMsg(String apiAddress, String params, String response) {
        apiAddressAPI = apiAddress;
        paramsAPI = params;
        responseAPI = response;
    }

    Response<T> response;
    Method setMessageMethod;
    Method setReturnCodeMethod;
    JSONObject jsonObject;

    /**
     * 从接口拿返回信息，并转换成实体类
     */
    public <T> T runAPI(Call call) {
        try {
            response = call.clone().execute();
            if (response.code() != 200) {
                Assert.assertTrue(false, "接口状态码不为200");
                return null;
            }
            //接口正常返回信息时，返回实体类
            T toBody = (T) response.body();
            if (toBody == null) {
                Assert.assertTrue(false, "接口返回信息结构可能发生变化");
            }
            return toBody;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 请求接口后，保存响应的信息
     */
    public <T> T runAPI(Call call,String apiName) {
        T toBody = this.runAPI(call);
        APImap.setApiMap(apiName, toBody);
        return toBody;
    }

    //添加错误信息到list  统一处理错误接口
    public void addErrMsg() {
        errDescription = errDescription.equals("") ? "接口返回码不为1000" : errDescription;
        emailContentBean = new EmailContentBean();
        emailContentBean.setApiName(apiNameAPI);
        emailContentBean.setDescription(errDescription);
        emailContentBean.setErrarAPIaddress(apiAddressAPI);
        emailContentBean.setParams(paramsAPI == null ? "showSize=18" : paramsAPI);
        emailContentBean.setResponse(responseAPI == null ? "404" : responseAPI);
        emailContentBean.setTime(dateFormat.format(new Date(System.currentTimeMillis())));
        list.add(emailContentBean);
        System.out.println(
            "\n========================================================\n" +
                "出错接口自我描述: " + errDescription + "\n" +
                "用例描述: " + apiNameAPI + "\n" +
                "接口地址: " + apiAddressAPI + "\n" +
                "接口参数: " + paramsAPI + "\n" +
                "接口返回: " + responseAPI
        );
    }

    //通过反射设置对象的值
    public void setClassParams(String methodName, Class<?> parameterTypes, Class c_getclass, Object objParams) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method m = c_getclass.getClass().getDeclaredMethod(methodName, parameterTypes);
        if (null != m) {
            m.invoke(c_getclass, objParams);
        }
    }

    /**
     * 将map参数转化为 RequestBody
     */
    public RequestBody toBody(Map<String, Object> map) {
        return FormBody.create(MediaType.parse("application/json"), JSON.toJSONString(map));
    }

    public void addErrMsg(String errDescription) {
        this.errDescription = errDescription;
//        addErrMsg();
    }
    public  void assertFalse(Boolean bl,String msg){
        Assert.assertFalse(bl,msg);
    }
    public  void assertTrue(Boolean bl,String msg){
        Assert.assertTrue(bl,msg);
    }
    public void addAllureMsg(String contentText) {
//        Allure.addAttachment();
    }
}
